package org.springmvc.web.servlet;

import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springmvc.constant.Constants;
import org.springmvc.web.context.WebApplicationContext;

import java.io.IOException;
import java.util.Locale;

/**
 * @author marin
 * @version 1.0
 * @date 2025/9/1 19:41
 * @desc 前端控制器
 */
@SuppressWarnings("all")
public class DispatcherServlet extends HttpServlet {

    /**
     * 视图解析器
     */
    private ViewResolver viewResolver;

    /**
     * 处理器映射器
     */
    private HandlerMapping handlerMapping;

    /**
     * 处理器适配器
     */
    private HandlerAdapter handlerAdapter;

    /**
     * 初始化数据
     * @throws ServletException
     */
    @Override
    public void init() throws ServletException {
        //获取配置对象
        ServletConfig servletConfig = getServletConfig();
        //获取springmvc的配置信息
        String configInitParameter = servletConfig.getInitParameter(Constants.CONTEXT_CONFIG_LOCATION);
        String absolutePath = "";
        if (configInitParameter.trim().startsWith(Constants.PREFIX_PATH)){//表示从类路径下加载资源
            String mvcFileName = configInitParameter.substring(Constants.PREFIX_PATH.length());
            //获取mvc配置文件的绝对路径
            absolutePath = Thread.currentThread().getContextClassLoader().getResource(mvcFileName).getPath();

        }
        //初始化spring容器
        WebApplicationContext webApplicationContext = new WebApplicationContext(getServletContext(),absolutePath);
        this.getServletContext().setAttribute(Constants.WEB_APPLICATION_CONTEXT,webApplicationContext);
        //初始化视图解析器
        this.viewResolver = (ViewResolver) webApplicationContext.getBean(Constants.VIEW_RESOLVER);
        //初始化处理器映射器
        this.handlerMapping = (HandlerMapping) webApplicationContext.getBean(Constants.HANDLER_MAPPING);
        //初始化处理器适配器
        this.handlerAdapter = (HandlerAdapter) webApplicationContext.getBean(Constants.HANDLER_ADAPTER);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doDispatch(req, resp);
    }

    /**
     * 处理请求的核心方法
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            //1. 根据请求对象获取处理器执行链
            HandlerExecutionChain mappedHandler = handlerMapping.getHandler(request);
            //2. 根据处理器方法获取处理器适配器
            HandlerAdapter ha = this.handlerAdapter;//正常是通过遍历获取对应的处理器映射器，但是我们写的只有一个。
            //3. 执行拦截器proHanler方法
            if (!mappedHandler.applyPreHandle(request, response)) {
                return;
            }
            //4. 获取ModelAndView对象
            ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler());
            //5. 执行拦截器postHanler方法
            mappedHandler.applyPostHandle(request, response, mv);
            //6.响应
            View view = viewResolver.resolveViewName(mv.getView().toString(), Locale.CHINA);
            //7.渲染
            view.render(mv.getModel(),request,response);
            //8. 执行拦截器AfterCompletion方法
            mappedHandler.triggerAfterCompletion(request, response, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
